#include <os/ioremap.h>
#include <os/mm.h>
#include <pgtable.h>
#include <type.h>
#include <os/sched.h>
// maybe you can map it to IO_ADDR_START ?
static uintptr_t io_base = IO_ADDR_START;

void *ioremap(unsigned long phys_addr, unsigned long size)
{
    // map phys_addr to a virtual address
    // then return the virtual address
    uint64_t kva;
    kva = pa2kva((uintptr_t)phys_addr);
    uint64_t ret=kva;
	PTE * pgtable_3rd;
    PTE * pgtable_2nd;
    PTE * pgtable = (PTE *)current_running->pgtable;
for(int i=0;i<size/NORMAL_PAGE_SIZE;i++){
	uint32_t vpn2 = GETVPN2(kva);
	uint32_t vpn1 = GETVPN1(kva);
	uint32_t vpn0 = GETVPN0(kva);
	uint64_t pa=kva2pa(kva);
    if(pgtable[vpn2]%2 == 0){
		pgtable_2nd = (PTE *)kmalloc_Page();
		pgtable_3rd = (PTE *)kmalloc_Page();
		pgtable[vpn2] = (uint64_t)PA2PTE(kva2pa((uintptr_t)pgtable_2nd))+KPGDIR_FLAG;
		pgtable_2nd[vpn1] = (uint64_t)PA2PTE(kva2pa((uintptr_t)pgtable_3rd))+KPGDIR_FLAG;
		pgtable_3rd[vpn0] = (uint64_t)PA2PTE(pa) + KPGTABLE_FLAG;
	}else {
        pgtable_2nd = (PTE *)pa2kva(PTE2PA(pgtable[vpn2]));
        if(pgtable_2nd[vpn1]%2 == 0){
            pgtable_3rd = kmalloc_Page();
            pgtable_2nd[vpn1] = (uint64_t)PA2PTE(kva2pa((uintptr_t)pgtable_3rd))+KPGDIR_FLAG;
            pgtable_3rd[vpn0] = (uint64_t)PA2PTE(pa) + KPGTABLE_FLAG;
        }else {
            pgtable_3rd = (PTE *)pa2kva(PTE2PA(pgtable_2nd[vpn1]));
            if(pgtable_3rd[vpn0]%2 == 0){
                pgtable_3rd[vpn0] = (uint64_t)PA2PTE(pa) + KPGTABLE_FLAG;
            }
        }
    }
    kva+=NORMAL_PAGE_SIZE;
}
    local_flush_tlb_all();
    return (void*)ret;
}

void iounmap(void *io_addr)
{
    // TODO: a very naive iounmap() is OK
    // maybe no one would call this function?
    // *pte = 0;
}
